<template>
  <div class="ts-learn">
    <h2>ts-learn</h2>
  </div>
</template>
<script lang="ts" setup>
import { onMounted } from "vue";

/* 基础类型标注
let isDone: boolean = false;
let price: number = 100;
let list: number[] = [1,2];
let list2: Array<number> = [1,2];
let tuple: [string,number] = ["1",2]; */

/* 接口 */
/* interface User {
    name: string;
    readonly age: number;
    gender?: string;
}

type addFunc = (a: number, b: number) => number;

const add: addFunc = (a, b) => {
    return a + b;
}

// console.log("add",add(1, 2))

let user: User = {
    name: "张三",
    age: 18,
    gender: "男"
}

console.log("user", user); */

/* interface User {
  name: string;
  age: number;
  gender: string;
}

interface Person extends User {
  height?: number;
}

interface ApiResponse<T> {
  code: number;
  data: T;
  message: string;
} */

// 范型参数既可以用interface定义，也可以用type定义

/* // 所有属性变为可选
type PartialPerson = Partial<Person>
 const userResonse: ApiResponse<PartialPerson> = {
    code: 200,
    data: {
        name: "张三"
    },
    message: "success"
} */

/* 所有属性变为只读
// 所有属性变为只读
type ReadonlyPerson = Readonly<Person>
const userResonse: ApiResponse<ReadonlyPerson> = {
    code: 200,
    data: {
        name: "张三",
        age: 18,
        gender: "男"
    },
    message: "success"
} 
userResonse.data.name = "李四";
console.log("userResonse", userResonse); */

/* 只挑选Person接口的name和age属性
// 只挑选Person接口的name和age属性
type PickPerson = Pick<Person, "name" | "age">
 const userResonse: ApiResponse<PickPerson> = {
    code: 200,
    data: {
        name: "张三",
        age: 18
    },
    message: "success"
}  */

/* 剔除Person接口的age属性
// 剔除Person接口的age属性
type OmitPerson = Omit<Person, "age">
const userResonse: ApiResponse<OmitPerson> = {
    code: 200,
    data: {
        name: "张三",
        gender: "男"
    },
    message: "success"
}   */

/* // 断言
onMounted(()=>{
    const tsLearn: Element | null = document.querySelector('.ts-learn');
    console.log("tsLearn",tsLearn)
}) */

// 装饰器

/* class Animal {
  constructor(public name: string) {}

  move(distance: number) {
    console.log(`${this.name} moved ${distance} meters.`);
  }
}

class Dog extends Animal {
  bark() {
    console.log("Woof! Woof!");
  }
}

const dog = new Dog("Buddy");
dog.move(10);
dog.bark(); */


/* 类装饰器
function ApiVersion(version: string) {
    return (target: Function) => {
        target.prototype.apiVersion = version;
        console.log(`API version ${version} applied to ${target.name}`);
        // console.log("target", target);
        // console.log("version", version);
    }
}


@ApiVersion("1.0.0")
class UserService {
    
}

const userService = new UserService();
const ret =  (userService as any).apiVersion;
console.log("userService", userService);
console.log("ret", ret); */


/* function ValidateEmail() {
  return (target: any, context: ClassFieldDecoratorContext) => {
    return function (initialValue: string) {
      let value = initialValue;

      const getter = () => value;
      const setter = (newValue: string) => {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailRegex.test(newValue)) {
          throw new Error(`Invalid email format for ${context.name}`);
        }
        value = newValue;
      };

      return {
        get: getter,
        set: setter,
        init: initialValue
      };
    };
  };
}


class User {
  @ValidateEmail()
  email: string;

  constructor(email: string) {
    this.email = email;
  }
}


try{
    const u = new User("123456");
}catch(e: any){
  console.log(e)
} */
interface Person {
    name: string;
    age: number;
}
interface Stu {
    grade: number;
}

/* 交叉类型：将多个类型合并为一个类型，新类型具有所有类型的特性
type PersonStu = Person & Stu;

const p: PersonStu = {
    name: "张三",
    age: 18,
    grade: 1
}

console.log("p", p); */

/* 联合类型：表示一个值可以是多种类型之一   
 type PersonStu = Person | Stu;

const p: PersonStu = {
    name: "张三",
    age: 18,
} */

// 获取一个类型的所有属性名（键）组成的 联合类型
type PersonKeys = keyof Person;

// function getProperty(obj: Person,key: PersonKeys) {
//     return obj[key];
// }

function getProperty<T,K extends keyof T>(obj: T,key: K): T[K] {
    return obj[key];
}



const person: Person = {name: '张三',age: 20}

console.log(getProperty(person,'name'));
console.log(getProperty(person,'age'));


</script>
<style scoped>
.ts-learn {
  padding: 10px;
}
</style>
